from django.db import models

###################
###    Rats    ####
###################

# rat table
class Rat(models.Model):
    #earring number
    """
    should I specify default (as a callback)? to check if some number is free 
    because some rat's dead. or I can just generate unique number every time 
    by making this field a primary key
    """
    eartag_number = models.IntegerField()
    
    # gender
    GENDER_CHOICES = (
        (u'M', u'Male'),
        (u'F', u'Female'),
    )
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
    
    # date of birth 
    date_of_birth = models.DateField()
    
    # genotype
    """
    should we do a definite list of possible values (like gender above)?
    """
    genotype = models.CharField(max_length = 100, blank = True)
    
    # rat's mother
    rat_mother = models.ForeignKey('self', blank = True, related_name = 'mother')
    
    # rat's father
    rat_father = models.ForeignKey('self', blank = True, related_name = 'father')
    
    # generation
    generation = models.CharField(blank = True, max_length = 100)
    
    ## state parameters ##
    
    # is it alive
    alive = models.BooleanField(default = True)
    
    # is it sick
    sick = models.BooleanField(default = False)
    
    # is it breeding
    breeding = models.BooleanField(default = False)
    
    # comments
    comments = models.TextField(blank = True)
    
    def __unicode__(self):
        return self.eartag_number

# breeding table
class Breed(models.Model):
    # male rat in a couple
    male_rat = models.ForeignKey(Rat, related_name = 'male_rat')
    
    # female rat in a couple
    female_rat = models.ForeignKey(Rat, related_name = 'female_rat')
    
    # breeding date
    breed_date = models.DateField()
    
    # breeding time
    breed_time = models.TimeField()
    
    # breeding result (offsprings number)
    breed_result = models.IntegerField(default = 0)
    
    def __unicode__(self):
        return self.rat.eartag_number
    
    
##########################
###    Experiments    ####
##########################

# experiment types table
class ExperimentType(models.Model):
    # name of an experiment
    name = models.CharField(max_length = 300)
    
    # description
    description = models.TextField()
    
    def __unicode__(self):
        return self.name

# tests sequence in an experiment table
class TestsSequenceForExperiment(models.Model):
    # experiment type
    experiment_type = models.ForeignKey(ExperimentType)
    
    # sequence number of the test in the experiment
    """
    how can we guarantee this number to be unique in context of an experiment?
    or how should we treat equal numbers?
    """
    sequence_number = models.IntegerField()
    
    # test type
    test_type = models.ForeignKey('TestType')
    
    def __unicode__(self):
        return self.experiment_type.name

# experiment instances table
class Experiment(models.Model):
    # experiment type
    experiment_type = models.ForeignKey(ExperimentType)
    
    # result
    result = models.TextField(blank = True)
    
    def __unicode__(self):
        return u"%(name)s (%(id)d)" % {'name' : self.experiment_type.name, 'id' : self.id}


####################
###    Tests    ####
####################

# test types table
class TestType(models.Model):
    # name of a test
    name = models.CharField(max_length = 300)
    
    # description
    description = models.TextField()
    
    # result format 
    """
    the purpose of this field is to be the list of result values with their 
    types. we will parse result string in a test instance using this format
    """
    result_format = models.TextField(blank = True)
        
    def __unicode__(self):
        return self.name
    
# tests sequence of subtests in a test
class TestsSequenceForTest(models.Model):
    # test type
    test_type = models.ForeignKey(TestType)
    
    # sequence number of a subtest
    sequence_number = models.IntegerField()
    
    # subtest type
    subtest_type = models.ForeignKey(TestType, related_name = 'subtest_type')
    
    def __unicode__(self):
        return self.test_type.name
    
# test instances table
class Test(models.Model): 
    # test type
    test_type = models.ForeignKey(TestType)
    
    # experiment in context of that this tests is performed
    experiment = models.ForeignKey(Experiment)
    
    # is it done yet
    done = models.BooleanField(default = False)
    
    # list of the rats involved in this test
    rats_involved = models.ManyToManyField(Rat, through = 'Assignment')
    
    # result
    result = models.TextField(blank = True)
    
    def __unicode__(self):
        return u"%(name)s (%(id)d)" % {'name' : self.test_type.name, 'id' : self.id}

# rat assignment class (relationship between a rat and a test)
class Assignment(models.Model):
    # rat
    rat = models.ForeignKey(Rat)
    
    # test instance
    test = models.ForeignKey(Test)
    
    # is it done yet
    done = models.BooleanField(default = False)
    
    # date for doing this test on this rat
    test_date = models.DateField()
    
    # time for doing this test on this rat
    test_time = models.TimeField()
    
    # result
    result = models.TextField(blank = True)

# tests compatibility table
class TestsCompatibility(models.Model):
    # test
    test_type = models.ForeignKey(TestType)
    
    # another test to check compatibility with
    """
    this should be a unique value in context of the base test
    """
    test_type_to_check_compatibility_with = models.ForeignKey(TestType, related_name = 'another_test_type')
    
    # are they compatible
    compatible = models.BooleanField(default = True)
    
    # explanation
    explanation = models.TextField(blank = True)
    
    def __unicode__(self):
        return self.test_type.name